﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Lacrima.Gobang.App
{
    internal class Chessboard
    {
        private Graphics graphics { get; set; }
        private Stone stone { get; set; }

        private static readonly object _syncObject = new object();
        //棋盘为15X15大小.数组中0表示黑子,1表示白子,2表示无子.
        public int[,] arrChessBoard = new int[15, 15];
        //判断当前是黑子还是白子
        private bool stoneflag = true;
        //电脑对象
        private Computer computer;
        //判断是谁先下子
        private bool mplayfirstflag = false; //true表示电脑先,执先手为黑子,默认为人先下
        //堆栈历史记录
        public System.Collections.Stack mStackHistory = new System.Collections.Stack();
        //下棋所用的步骤
        public int[,] ArrStep = new int[15, 15];//记录下子的步骤,如果在该点上尚未下子,即没有步骤则为0
        //下棋所用步骤计数器
        public int step;
        //从棋谱文档里读出来的棋谱数组
        public string[] ArrQP = new string[255];
        //观看下棋录像和正常下棋的区别标志,0表示录像,1表示正常下棋(人与电脑对弈,默认值)
        public int WhoDownFlag = 1;
        //棋谱的步骤数
        public int QPStepNum = 1;
        /// <summary>
        /// 棋盘横坐标的值
        /// </summary>
        enum ChessBoard_X
        {
            A, B, C, D, E, F, G, H, I, J, K, L, M, N, O
        };
        public string[] ChessBoard_Y = { "15", "14", "13", "12", "11", "10", "9", "8", "7", "6", "5", "4", "3", "2", "1" };


        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="g"></param>
        public Chessboard(Graphics g)
        {
            graphics = g;
            Initialization();
            stone = new Stone(graphics);
        }

        #region 初始化
        /// <summary>
        /// 初始化
        /// </summary>
        public void Initialization()
        {
            //初始化,最开始为黑子(true)先下
            stoneflag = true;
            for (int i = 0; i < 15; i++)
            {
                for (int j = 0; j < 15; j++)
                {
                    arrChessBoard[i, j] = 2;
                    //清空数字标记
                    ArrStep[i, j] = 0;
                }
            }
            step = 0;
            mStackHistory.Clear();
            //默认初始化为电脑后下棋
            computer = new Computer(false);
        }
        #endregion

        public void Start()
        {
            //初始化
            Initialization();
            computer = new Computer(mplayfirstflag);
            Draw();
            if (mplayfirstflag == true)
            {
                //电脑先下
                ComputerDownStone();
            }
        }
        public void Start(bool firstplay)
        {
            mplayfirstflag = firstplay;
            Start();
        }
        public void Draw()
        {
            lock (_syncObject)
            {
                //读取棋盘图像
                //从资源中获取
                Image imgChessboard = global::Lacrima.Gobang.App.Properties.Resources.chessboard; //棋盘图片 大小600*600像素

                graphics.DrawImage(imgChessboard, 0, 24, imgChessboard.Width, imgChessboard.Height);
                //重绘棋盘            
                for (int i = 0; i < 15; i++)
                {
                    for (int j = 0; j < 15; j++)
                    {
                        //画黑子(true,0)
                        if (arrChessBoard[i, j] == 0) stone.DrawStone(i, j, true, ArrStep[i, j]);
                        if (arrChessBoard[i, j] == 1) stone.DrawStone(i, j, false, ArrStep[i, j]);
                    }
                }
                if (WhoDownFlag == 0)
                {
                    //画出提示字
                    Brush brh = new SolidBrush(Color.Blue);
                    System.Drawing.Font f = new Font("宋体", 30);
                    graphics.DrawString("正在查看棋谱录像中...", f, brh, 100, 300);
                }
            }
        }

        public void PersonDownStone(int x, int y)
        {
            //转化棋盘点            
            int m, n;
            m = (int)((double)x / 40);
            n = (int)((double)y / 40);
            if (!Rule.IsExists(m, n, arrChessBoard))
            {
                //如果在该点上不存在子.则下一个棋子
                DownStone(m, n);
                ComputerDownStone();
            }
        }

        private void ComputerDownStone()
        {
            //电脑下棋
            try
            {
                int m, n, count = 0;
                computer.DownDot(arrChessBoard);
                m = computer.M;
                n = computer.N;
                count++;
                DownStone(m, n);
            }
            catch (Exception ex)
            {
                MessageBox.Show("程序出错了:" + ex.Message, "温馨提示", MessageBoxButtons.OK);
            }
        }

        private void DownStone(int m, int n)
        {
            #region 人机对弈,下子
            //用于显示X坐标的值
            string Xname = "";
            string[] XN = Enum.GetNames(typeof(ChessBoard_X));
            Xname = XN[m];
            //下棋子的步骤计数器
            step++;
            //下一个棋子
            stone.DrawStone(m, n, stoneflag, step);
            //黑子存入数组
            if (stoneflag == true)
            {
                arrChessBoard[m, n] = 0;
            }
            //白子存入数组
            else
            {
                arrChessBoard[m, n] = 1;
            }

            //黑子存入棋子步骤
            if (stoneflag == true)
            {
                //修改：2018年1月20日23:02:15，仇士龙，修改棋谱显示方式
                //mStackHistory.Push(step.ToString() + " " + "黑子 x:" + Xname + "-" + "y:" + ChessBoard_Y[n].ToString());
                mStackHistory.Push(step.ToString() + " " + "黑方：" + Xname + ChessBoard_Y[n].ToString());
            }
            //白子存入棋子步骤
            else
            {
                //修改：2018年1月20日23:02:15，仇士龙，修改棋谱显示方式
                mStackHistory.Push(step.ToString() + " " + "白子：" + Xname + ChessBoard_Y[n].ToString());
            }

            //保存步骤
            ArrStep[m, n] = step;
            //判断结果
            //System.Windows.Forms.MessageBox.Show(Rule.FIR_Result(m, n, arrChessBoard).ToString());
            if (Rule.FIR_Result(m, n, arrChessBoard) < 6)
            {
                switch (Rule.FIR_Result(m, n, arrChessBoard))
                {
                    case 1:
                        MessageBox.Show("黑子双三禁手!", "温馨提示", MessageBoxButtons.OK);
                        break;
                    case 2:
                        MessageBox.Show("黑子双四禁手!", "温馨提示", MessageBoxButtons.OK);
                        break;
                    case 3:
                        MessageBox.Show("黑子长联禁手!", "温馨提示", MessageBoxButtons.OK);
                        break;
                    case 4:
                        string txtStone = "";
                        if (stoneflag == true) txtStone = "黑子胜利";
                        else txtStone = "白子胜利";
                        if (MessageBox.Show(txtStone, "是否保存棋谱", System.Windows.Forms.MessageBoxButtons.YesNo) == DialogResult.Yes)
                        {
                            SaveQP();
                        }
                        break;
                    case 5:
                        System.Windows.Forms.MessageBox.Show("平局!");
                        break;
                }
                //重新开始
                Start();
            }
            else stoneflag = !stoneflag;//重新开始 
            #endregion
        }
        /// <summary>
        /// 保存棋谱
        /// </summary>
        public void SaveQP()
        {
            try
            {
                //保存棋谱
                string tempstr = "";
                Array arr = mStackHistory.ToArray();
                if (arr.Length > 0)
                {
                    for (int i = arr.Length - 1; i >= 0; i--)
                    {
                        tempstr += arr.GetValue(i).ToString() + "\r\n";
                    }
                    tempstr += "CreateBy liqiang665@163.com QQ:16826375\r\n";
                    tempstr += System.DateTime.Now.ToString();
                    SaveFileDialog sd = new SaveFileDialog();
                    sd.Filter = "文本文件(*.txt)|*.txt";
                    if (sd.ShowDialog() == DialogResult.OK)
                    {
                        //保存文件
                        FileStream fs = new FileStream(sd.FileName, FileMode.Create, FileAccess.ReadWrite);
                        StreamWriter sw = new StreamWriter(fs, Encoding.GetEncoding("gb2312"));
                        sw.Write(tempstr);
                        sw.Flush();
                        sw.Close();
                        fs.Close();
                    }
                }
                else MessageBox.Show("没有可用棋谱", "温馨提示", MessageBoxButtons.OK);
            }
            catch
            {
                MessageBox.Show("程序错误,保存失败", "温馨提示", MessageBoxButtons.OK);
            }
        }
        public void OpenQP()
        {
            try
            {
                OpenFileDialog ofd = new OpenFileDialog();
                ofd.Filter = "文本文件(*.txt)|*.txt";
                if (ofd.ShowDialog() == DialogResult.OK)
                {
                    //打开文件成功
                    StreamReader sd = new StreamReader(ofd.FileName, Encoding.GetEncoding("gb2312"));
                    string tempstr = "";
                    tempstr = sd.ReadToEnd();
                    tempstr = tempstr.Replace("\r\n", "\r");
                    //旧的有说明的棋谱数组
                    string[] arrstr = tempstr.Split('\r');
                    for (int i = 0; i < arrstr.Length; i++)
                    {
                        //循环输出,直到不是棋谱为止
                        if (IsNum(arrstr[i].Substring(0, 1)) == false) break;
                        ArrQP[i] = arrstr[i];
                        //因为i是从0开始,所以这里不减,有效棋谱行数
                        QPStepNum = i;
                    }
                    //MessageBox.Show(tempstr);
                    if (QPStepNum == 1) MessageBox.Show("错误的棋谱文件", "温馨提示", MessageBoxButtons.OK);
                }
            }
            catch
            {
                MessageBox.Show("错误的棋谱格式", "温馨提示", MessageBoxButtons.OK);
            }
        }
        private bool IsNum(string numxtr)
        {
            //检查是否数字
            try
            {
                int.Parse(numxtr);
                return true;
            }
            catch
            {
                return false;
            }
        }
    }
}
